<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
class myPromise {
  constructor(executor) {
      this.state = 'pending';
      this.result = null;
      this.reason = null;
      this.onFulfilledCallbacks = [];
      this.onRejectedCallbacks = [];
      try {
           executor(this.resolve.bind(this), this.reject.bind(this));
      } catch (error) {
          this.reject(error)
      }
  }
  resolve(result) {
      if (this.state === 'pending') {
          this.state = 'fulfilled';
          this.result = result;
          this.onFulfilledCallbacks.forEach(callback => {
              callback(result)
          })
      }
  }
  reject(reason) {
      if (this.state === 'pending') {
          this.state = 'rejected';
          this.reason = reason;
          this.onRejectedCallbacks.forEach(callback => {
              callback(reason)
          })
      }
  }
  then(onFulfilled, onRejected) {
      let promise2 = new myPromise((resolve, reject) => {
          if (this.state === 'fulfilled') {
              setTimeout(() => {
                  try {
                      if (typeof onFulfilled !== 'function') {
                          resolve(this.result);
                      } else {
                          let x = onFulfilled(this.result);
                          resolvePromise(promise2, x, resolve, reject);
                      }
                  } catch (e) {
                      reject(e);
                  }
              });
          } else if (this.state === 'rejected') {
              setTimeout(() => {
                  try {
                      if (typeof onRejected !== 'function') {
                          reject(this.reason);
                      } else {
                          let x = onRejected(this.reason);
                          resolvePromise(promise2, x, resolve, reject);
                      }
                  } catch (e) {
                      reject(e)
                  }
              });
          } else if (this.state === 'pending') {
              this.onFulfilledCallbacks.push(() => {
                  setTimeout(() => {
                      try {
                          if (typeof onFulfilled !== 'function') {
                              resolve(this.result);
                          } else {
                              let x = onFulfilled(this.result);
                              resolvePromise(promise2, x, resolve, reject);
                          }
                      } catch (e) {
                          reject(e);
                      }
                  });
              });
              this.onRejectedCallbacks.push(() => {
                  setTimeout(() => {
                      try {
                          if (typeof onRejected !== 'function') {
                              reject(this.reason);
                          } else {
                              let x = onRejected(this.reason);
                              resolvePromise(promise2, x, resolve, reject);
                          }
                      } catch (e) {
                          reject(e);
                      }
                  });
              });
          }
      })
      return promise2
  }
}
function resolvePromise(promise2, x, resolve, reject) {
  if (x === promise2) {
      throw new TypeError('promise error');
  }
  if (x instanceof myPromise) {
      x.then(y => {
          resolvePromise(promise2, y, resolve, reject)
      }, reject);
  } else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
      try {
          var then = x.then;
      } catch (e) {
          return reject(e);
      }
      if (typeof then === 'function') {
          let called = false;
          try {
              then.call(
                  x,
                  y => {
                      if (called) return;
                      called = true;
                      resolvePromise(promise2, y, resolve, reject);
                  },
                  r => {
                      if (called) return;
                      called = true;
                      reject(r);
                  }
              )
          } catch (e) {
              if (called) return;
              called = true;
              reject(e);
          }
      } else {
          resolve(x);
      }
  } else {
      return resolve(x);  
  }
}
  </script>
</body>
</html>